# -*- coding: utf-8 -*-
"""
core/需求分析/analyzer.py

需求分析与差异识别模块。
负责对比新旧需求文档，输出结构化的差异报告。
"""

import os
import json
from core.utils import logger, read_file_content, write_json_file
from openai import OpenAI

# DeepSeek API配置
LLM_API_KEY = "sk-c06f710a39384af3a80e46acb699b0e5"  # DeepSeek API密钥
LLM_API_BASE_URL = "https://api.deepseek.com"  # DeepSeek API基础URL
LLM_MODEL = "deepseek-chat"  # 使用的模型

def call_llm_for_requirement_diff(old_req_content, new_req_content):
    """
    调用DeepSeek LLM API来分析需求差异。

    参数:
        old_req_content (str): 旧需求文档的内容。
        new_req_content (str): 新需求文档的内容。

    返回:
        list: 包含差异项的列表，每个差异项是一个字典。
              例如: [{'type': '新增', 'feature_name': '童锁功能', 'new_description': '新增长按组合键3秒进入/退出童锁模式功能。', 'old_description': '', 'details': '这是一个全新的功能，旨在防止儿童误操作。'},
                    {'type': '修改', 'feature_name': '电量显示逻辑', 'new_description': '电压低于3.2V显示1格电，低于3.0V闪烁。', 'old_description': '旧电量显示逻辑', 'details': '调整了电量显示的阈值和提示方式，以提供更准确的低电量预警。'}]
              如果API调用失败或解析失败，返回空列表。
    """
    logger.info("开始调用LLM进行需求差异分析...")
    
    # 构建发送给LLM的提示 (prompt)
    prompt = f"""
    请仔细对比以下两份嵌入式产品需求文档：

    旧需求文档内容如下：
    --- 旧需求开始 ---
    {old_req_content}
    --- 旧需求结束 ---

    新需求文档内容如下：
    --- 新需求开始 ---
    {new_req_content}
    --- 新需求结束 ---

    请分析新需求相对于旧需求的变化，识别出所有'新增功能'、'修改功能'和'移除功能'。
    请以JSON格式的列表返回结果，列表中每个对象代表一个变更点，并包含以下字段：
    - "type": 变更类型，字符串，可选值为 "新增"、"修改"、"移除"。
    - "feature_name": 功能点名称，字符串，例如 "童锁保护"、"电量显示"。
    - "new_description": 对于'新增'或'修改'类型，这是新功能或修改后功能的详细描述，字符串。
    - "old_description": 对于'修改'或'移除'类型，这是旧功能的描述，字符串。对于'新增'类型，此字段应为空字符串或省略。
    - "details": 对变更的补充说明或具体变更点，字符串。

    确保输出是严格的JSON格式列表。例如：
    [
      {{
        "type": "新增",
        "feature_name": "童锁保护",
        "new_description": "长按特定组合键3秒后进入或退出童锁模式。童锁模式下，除解锁键外所有按键无效，特定LED指示状态。",
        "old_description": "",
        "details": "这是一个全新的功能，旨在防止儿童误操作。"
      }},
      {{
        "type": "修改",
        "feature_name": "电量显示",
        "new_description": "当电压低于3.2V时显示1格电量，低于3.0V时LED闪烁提示低电量。",
        "old_description": "旧版电量显示分为4格，分别对应3.8V, 3.5V, 3.2V, 3.0V。",
        "details": "调整了电量显示的阈值和提示方式，以提供更准确的低电量预警。"
      }}
    ]
    """

    logger.debug(f"发送给LLM的提示: \n{prompt[:500]}...") # 打印部分提示词用于调试

    try:
        # 调用DeepSeek API
        client = OpenAI(
            api_key=LLM_API_KEY,
            base_url=LLM_API_BASE_URL
        )
        
        response = client.chat.completions.create(
            model=LLM_MODEL,
            messages=[
                {"role": "system", "content": "你是一个专业的需求分析师，擅长对比新旧需求并输出结构化的差异分析。请确保输出严格按照要求的JSON格式。"},
                {"role": "user", "content": prompt}
            ],
            stream=False
        )
        
        # 获取API响应
        response_content = response.choices[0].message.content
        logger.info("LLM API调用成功，收到响应。")
        
        # 从响应文本中提取JSON部分
        json_start = response_content.find('[')
        json_end = response_content.rfind(']') + 1
        
        if json_start != -1 and json_end != -1:
            json_str = response_content[json_start:json_end]
            diff_list = json.loads(json_str)
            logger.info(f"成功解析LLM响应，识别出 {len(diff_list)} 项需求差异。")
            return diff_list
        else:
            logger.error("无法从LLM响应中提取JSON数据")
            logger.error(f"LLM原始响应: {response_content}")
            return []
            
    except Exception as e:
        logger.error(f"调用LLM API或解析响应时出错: {e}")
        return []

def analyze_requirements(old_req_file_path, new_req_file_path, output_json_path):
    """
    需求分析模块的主函数。

    参数:
        old_req_file_path (str): 旧需求文档的路径。
        new_req_file_path (str): 新需求文档的路径。
        output_json_path (str): 分析结果（差异列表）的输出JSON文件路径。

    返回:
        list: 需求差异列表，如果处理失败则返回空列表。
    """
    logger.info(f"开始需求分析：旧需求文件 '{old_req_file_path}', 新需求文件 '{new_req_file_path}'")

    old_req_content = read_file_content(old_req_file_path)
    new_req_content = read_file_content(new_req_file_path)

    if old_req_content is None:
        logger.error(f"无法读取旧需求文件内容: {old_req_file_path}")
        return []
    if new_req_content is None:
        logger.error(f"无法读取新需求文件内容: {new_req_file_path}")
        return []
    
    logger.info("旧需求和新需求文件内容已成功读取。")

    requirement_diff_list = call_llm_for_requirement_diff(old_req_content, new_req_content)

    if requirement_diff_list:
        if write_json_file(output_json_path, requirement_diff_list):
            logger.info(f"需求差异分析结果已成功保存到: {output_json_path}")
        else:
            logger.error(f"保存需求差异分析结果失败: {output_json_path}")
    else:
        logger.warning("未能从LLM获取或解析需求差异列表。")

    return requirement_diff_list

if __name__ == "__main__":
    # 设置项目根目录，以便脚本可以从任何地方运行
    # 通常这个会在主脚本中设置，或者通过环境变量
    project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) 
    # embedded_code_gen_system/core/需求分析 -> embedded_code_gen_system/core -> embedded_code_gen_system
    
    # 定义输入输出文件路径 (相对于项目根目录)
    # 注意：这些文件需要实际存在才能成功运行
    # 我们将在主脚本中确保这些文件被正确放置
    mock_old_req_file = os.path.join(project_root, "data", "input", "old_requirements.md")
    mock_new_req_file = os.path.join(project_root, "data", "input", "new_requirements.md")
    output_file = os.path.join(project_root, "data", "output", "requirement_diff.json")

    # 为了独立测试，创建临时的模拟输入文件
    os.makedirs(os.path.dirname(mock_old_req_file), exist_ok=True)
    os.makedirs(os.path.dirname(mock_new_req_file), exist_ok=True)
    os.makedirs(os.path.dirname(output_file), exist_ok=True)

    # 写入模拟的旧需求内容
    with open(mock_old_req_file, "w", encoding="utf-8") as f_old:
        f_old.write("""
        # TM56F1522-V1.0-OLD 功能说明

        ## 1. 按键功能
        - 短按模式键切换工作模式。
        - 短按加键增加参数。
        - 短按减键减少参数。

        ## 2. LED显示
        - LED1指示电源状态。
        - LED2指示工作模式A。
        - LED3指示工作模式B。
        - 电量显示通过4个LED灯分别表示25%、50%、75%、100%的电量。

        ## 3. 定时提醒
        - 每隔1小时蜂鸣器响一声。
        """)
    
    # 写入模拟的新需求内容 (与用户提供的 新需求说明.md 类似)
    with open(mock_new_req_file, "w", encoding="utf-8") as f_new:
        f_new.write("""
        # 新嵌入式设备功能需求 V1.1

        ## 1. 童锁保护功能 (新增)
        - 长按【模式键】+【加键】3秒，进入或退出童锁模式。
        - 童锁模式下，所有按键（除解锁组合键外）无效。
        - LED4用于指示童锁状态（激活时常亮）。

        ## 2. 电量显示逻辑 (修改)
        - 当电池电压低于3.2V时，LED1显示1格电量（常亮）。
        - 当电池电压低于3.0V时，LED1闪烁提示低电量。
        - 移除旧的多级LED电量显示方式。

        ## 3. 按键功能调整 (修改)
        - 短按模式键仍然切换工作模式。
        - 长按模式键进入设置菜单。

        ## 4. 移除定时提醒功能 (移除)
        - 不再需要每小时的蜂鸣器提醒。
        """)

    logger.info(f"需求分析模块独立测试开始，项目根目录: {project_root}")
    logger.info(f"旧需求文件: {mock_old_req_file}")
    logger.info(f"新需求文件: {mock_new_req_file}")
    logger.info(f"输出差异文件: {output_file}")

    diffs = analyze_requirements(mock_old_req_file, mock_new_req_file, output_file)

    if diffs:
        logger.info("需求分析模块测试成功完成。差异内容：")
        for item in diffs:
            logger.info(f"  类型: {item.get('type')}, 功能名: {item.get('feature_name')}, 新描述: {item.get('new_description', 'N/A')}, 旧描述: {item.get('old_description', 'N/A')}")
    else:
        logger.error("需求分析模块测试失败或未产生差异。")


